#include "FKAbstractObjectManager.h"

//#include <QThread>
#include <QVariant>
#include <QSettings>

#include "FKEvent.h"
#include "FKClient.h"

#include "FKPaths.h"
#include "FKLogger.h"

FKAbstractObjectManager::FKAbstractObjectManager():QObject(){
    FK_CBEGIN
    _client=0;
//    _thread=new QThread;
//    _thread->start();
//    moveToThread(_thread);
    _clientAccs=staticInitClients();
    FK_CEND
}

FKAbstractObjectManager::~FKAbstractObjectManager(){
    FK_DBEGIN
//    _thread->quit();
//    _thread->deleteLater();
    FKObject::deleteAll();
    FK_DEND
}

void FKAbstractObjectManager::externalEvent(FKEvent* event){
    returnMessage(event->client(), QString("Object manager does not support external events"));
    event->deleteLater();
}

void FKAbstractObjectManager::clientRequested(QString clientName, QString password){
    getClient(clientName,password,0);
}

void FKAbstractObjectManager::internalEvent(FKEvent* event){
    if(event->recievers().contains(-1)){
        if(getLocalClient()){
            getLocalClient()->manageEvent(event);
        }else{
            returnMessage(event->client(), QString("No client for internal event"));
            event->deleteLater();
        }
    }else if(event->recievers().contains(-2)){
        if(getLocalClient() && event->recievers().contains(getLocalClient()->getID())){
            getLocalClient()->manageEvent(event);
        }else{
//            returnMessage(event->client(), QString("No client for internal event"));
            event->deleteLater();
        }
    }else{
        event->deleteLater();
    }
}

void FKAbstractObjectManager::action(FKEvent* action){
    FKClient* client=qobject_cast<FKClient*>(FKObject::getObject(action->client()));
    if(client){
        client->manageAction(action);
    }else{
        returnMessage(action->client(), QString("manager failed find client to pass action"));
        action->deleteLater();
    }
}

//FKClient* FKAbstractObjectManager::createClient(FKEvent* client){

//}

void FKAbstractObjectManager::setLocalClient(FKClient* client){
    _client=client;
    client->setConnected();
    emit clientSetted(client);
}

FKClient* FKAbstractObjectManager::getLocalClient(){
    return _client;
}

void FKAbstractObjectManager::showMessage(QString text){
    emit message(text);
}

void FKAbstractObjectManager::genClient(QString clientName, QString password){
    genClient(clientName,password,QVariant());
}

void FKAbstractObjectManager::genClient(QString clientName, QString password, QVariant validator){
    genClient(clientName,password,validator,0);
}

void FKAbstractObjectManager::genClient(QString clientName, QString password, QVariant validator, FKClientManager *s){
    QString message(clientGeneration(clientName,password,validator));
    if(s){
        sendMessage(message,s);
    }else{
        showMessage(message);
    }
}

void FKAbstractObjectManager::sendMessage(QString message, FKClientManager *manager){
    Q_UNUSED(manager)
    FK_MLOG(QString("Message from object manager: ")+message)
}

QString FKAbstractObjectManager::clientGeneration(QString clientName, QString password, QVariant validator){
    if(validateClientData(clientName,password)){
        if(regClient(clientName,password,validator)){
            return QString(tr("Client successfully created: "))+clientName;
        }else{
            return QString(tr("Failed create client"));
        }
    }else{
        return QString(tr("Failed create client: invalid name or password"));
    }
}

bool FKAbstractObjectManager::validateClientData(QString clientName, QString password){
    return clientName != QString() && password != QString();
}

bool FKAbstractObjectManager::regClient(QString clientName, QString password, QVariant validator){
    Q_UNUSED(validator)
    if(_clientAccs.contains(clientName)){
        return false;
    }else{
        QSettings clients;
        _clientAccs.insert(clientName,password);
        clients.setValue(FKPaths::clients,_clientAccs);
        return true;
    }
}


QMap<QString,QVariant> FKAbstractObjectManager::staticInitClients(){
    QSettings settings;
//    settings.remove("");
    QVariant s(settings.value(FKPaths::clients));
    QMap<QString,QVariant> m;
    if(s!=QVariant()){
        m=s.toMap();
    }else{
        m[FKPaths::localClient]=FKPaths::localClientPassword;
        settings.setValue(FKPaths::clients,m);
    }
    return m;
}

QString FKAbstractObjectManager::checkClient(QString clientName, QString password){
    if(validateClientData(clientName,password)){
        QString n(_clientAccs.value(clientName,QVariant()).toString());
        if(n!=QString()){
            if(n==password){
                return QString();
            }else{
                return QString(tr("Invalid password"));
            }
        }else{
            return QString(tr("Invalid client name"));
        }
    }else{
        return QString(tr("Invalid client name or password"));
    }
}

FKClient* FKAbstractObjectManager::catchClient(QString clientName,QString password){
    FKClient* client=FKClient::getClient(clientName);
    if(!client){
        client=new FKClient(clientName,password);
        client->setServerFiles(serverFiles());
    }else{
        client->beginReconnect();
    }
    return client;
}
